package cn.snmp.mutual.org.opennms.protocols.snmp;

import java.util.*;

import cn.snmp.mutual.org.opennms.protocols.snmp.asn1.AsnDecodingException;
import cn.snmp.mutual.org.opennms.protocols.snmp.asn1.AsnEncoder;
import cn.snmp.mutual.org.opennms.protocols.snmp.asn1.AsnEncodingException;

public class SnmpPduTrap implements SnmpSyntax, Cloneable {
    private SnmpObjectId m_enterprise;
    private SnmpIPAddress m_agentAddr;
    private int m_generic;
    private int m_specific;
    private long m_tstamp;
    private ArrayList m_variables;
    public static final int TRAP = 164;
    public static final int GenericColdStart = 0;
    public static final int GenericWarmStart = 1;
    public static final int GenericLinkDown = 2;
    public static final int GenericLinkUp = 3;
    public static final int GenericAuthenticationFailure = 4;
    public static final int GenericEgpNeighborLoss = 5;
    public static final int GenericEnterpriseSpecific = 6;

    public SnmpPduTrap() {
        this.m_enterprise = new SnmpObjectId();
        this.m_agentAddr = new SnmpIPAddress();
        this.m_generic = 0;
        this.m_specific = 0;
        this.m_tstamp = 0L;
        this.m_variables = new ArrayList();
    }

    protected SnmpPduTrap(final SnmpPduTrap second) {
        this.m_enterprise = second.m_enterprise;
        this.m_agentAddr = second.m_agentAddr;
        this.m_generic = second.m_generic;
        this.m_specific = second.m_specific;
        this.m_tstamp = second.m_tstamp;
        this.m_variables = new ArrayList(second.m_variables.size());
        for (int x = second.m_variables.size() - 1; x >= 0; --x) {
            this.m_variables.set(x, ((SnmpVarBind) second.m_variables.get(x)).duplicate());
        }
    }

    public SnmpObjectId getEnterprise() {
        return this.m_enterprise;
    }

    public void setEnterprise(final SnmpObjectId id) {
        this.m_enterprise = (SnmpObjectId) id.clone();
    }

    public void setEnterprise(final String id) {
        this.m_enterprise = new SnmpObjectId(id);
    }

    public SnmpIPAddress getAgentAddress() {
        return this.m_agentAddr;
    }

    public void setAgentAddress(final SnmpIPAddress addr) {
        this.m_agentAddr = addr;
    }

    public int getGeneric() {
        return this.m_generic;
    }

    public void setGeneric(final int generic) {
        this.m_generic = generic;
    }

    public int getSpecific() {
        return this.m_specific;
    }

    public void setSpecific(final int spec) {
        this.m_specific = spec;
    }

    public long getTimeStamp() {
        return this.m_tstamp;
    }

    public void setTimeStamp(final long ts) {
        this.m_tstamp = ts;
    }

    public int getLength() {
        return this.m_variables.size();
    }

    public void addVarBind(final SnmpVarBind vb) {
        this.m_variables.add(vb);
    }

    public void addVarBindAt(final int ndx, final SnmpVarBind vb) {
        this.m_variables.add(ndx, vb);
    }

    public SnmpVarBind getVarBindAt(final int ndx) {
        return (SnmpVarBind) this.m_variables.get(ndx);
    }

    public void setVarBindAt(final int ndx, final SnmpVarBind vb) {
        this.m_variables.set(ndx, vb);
    }

    public SnmpVarBind removeVarBindAt(final int ndx) {
        return (SnmpVarBind) this.m_variables.remove(ndx);
    }

    public SnmpVarBind[] toVarBindArray() {
        final Object[] list = this.m_variables.toArray();
        final SnmpVarBind[] vblist = new SnmpVarBind[list.length];
        for (int x = 0; x < list.length; ++x) {
            vblist[x] = (SnmpVarBind) list[x];
        }
        return vblist;
    }

    public byte typeId() {
        return -92;
    }

    public int encodeASN(final byte[] buf, int offset, final AsnEncoder encoder) throws AsnEncodingException {
        final int begin = offset;
        offset = this.m_enterprise.encodeASN(buf, offset, encoder);
        offset = this.m_agentAddr.encodeASN(buf, offset, encoder);
        final SnmpInt32 val = new SnmpInt32(this.m_generic);
        offset = val.encodeASN(buf, offset, encoder);
        val.setValue(this.m_specific);
        offset = val.encodeASN(buf, offset, encoder);
        final SnmpTimeTicks val2 = new SnmpTimeTicks(this.m_tstamp);
        final int vbbegin;
        offset = (vbbegin = val2.encodeASN(buf, offset, encoder));
        for (int sz = this.m_variables.size(), x = 0; x < sz; ++x) {
            final SnmpVarBind ref = (SnmpVarBind) this.m_variables.get(x);
            offset = ref.encodeASN(buf, offset, encoder);
        }
        int pivot = offset;
        offset = encoder.buildHeader(buf, offset, (byte) 48, pivot - vbbegin);
        SnmpUtil.rotate(buf, vbbegin, pivot, offset);
        pivot = offset;
        offset = encoder.buildHeader(buf, offset, this.typeId(), pivot - begin);
        SnmpUtil.rotate(buf, begin, pivot, offset);
        return offset;
    }

    public int decodeASN(final byte[] buf, int offset, final AsnEncoder encoder) throws AsnDecodingException {
        Object[] rVals = encoder.parseHeader(buf, offset);
        offset = (int) rVals[0];
        int cmd = (int) rVals[1];
        int length = (int) rVals[2];
        int begin = offset;
        if (cmd < 0) {
            cmd += 256;
        }
        if (164 != cmd) {
            throw new AsnDecodingException("Invalid SNMP command, Not a Trap");
        }
        offset = this.m_enterprise.decodeASN(buf, offset, encoder);
        offset = this.m_agentAddr.decodeASN(buf, offset, encoder);
        final SnmpInt32 val = new SnmpInt32();
        offset = val.decodeASN(buf, offset, encoder);
        this.m_generic = val.getValue();
        offset = val.decodeASN(buf, offset, encoder);
        this.m_specific = val.getValue();
        final SnmpTimeTicks val2 = new SnmpTimeTicks();
        offset = val2.decodeASN(buf, offset, encoder);
        this.m_tstamp = val2.getValue();
        rVals = encoder.parseHeader(buf, offset);
        offset = (int) rVals[0];
        length = (int) rVals[2];
        final byte asnType = (byte) rVals[1];
        if (asnType != 48) {
            throw new AsnDecodingException("Invalid SNMP variable list");
        }
        begin = offset;
        this.m_variables.clear();
        final SnmpVarBind vb = new SnmpVarBind();
        while (length > 0) {
            offset = vb.decodeASN(buf, offset, encoder);
            length -= offset - begin;
            begin = offset;
            this.m_variables.add(vb.duplicate());
        }
        return offset;
    }

    public SnmpSyntax duplicate() {
        return new SnmpPduTrap(this);
    }

    public Object clone() {
        return new SnmpPduTrap(this);
    }
}
